(* Copyright (C) 2010 School of Software Engineering, 
 * University of Science and Technology of China.
 *
 * This code is released under a BSD-style license.
 * See the file LICENSE for details.
 *)

functor Parser (S: PARSER_STRUCTS): PARSER = 
struct

open S
open ByteCode
open Command CodeHeap

exception Error
exception UnexpectedInput

val errorNum = ref 0
val errorLimit = 5

fun error (s) = 
    let val _ = print (String.concat ["Error: ", s, "\n"])
        val _ = errorNum := !errorNum + 1
    in  if (!errorNum >= errorLimit)
        then raise Error
        else []
    end

fun parseNum char= Char.ord char - Char.ord #"0"

fun parse (cs: char list): Command.t list =
    case cs
     of [] => []
      | t::tail =>
        (case t 
          of #"p" => Pop :: parse tail 
           | #"+" => Add :: parse tail
           | #"-" => Sub :: parse tail
           | #"s" => Swap :: parse tail
           | #"c" => (case tail of 
		          [] => error ("push wants an operand")
		        | num::tail =>
		          Push (parseNum num)::parse tail)
           | #"j" => (case tail of 
		          [] => error ("jump wants an operand")
		        | num::tail =>
		          Jump (parseNum num)::parse tail)
           | #"=" => (case tail of 
		          [] => error ("jeq wants an operand")
		        | num::tail =>
		          Jeq (parseNum num)::parse tail)
           | #"<" => (case tail of 
		          [] => error ("jlt wants an operand")
		        | num::tail =>
		          Jlt (parseNum num)::parse tail)
           | #"r" => (case tail of 
		          [] => error ("load wants an operand")
		        | num::tail =>
		          Load (parseNum num)::parse tail)
           | #"w" => (case tail of 
		          [] => error ("store wants an operand")
		        | num::tail =>
		          Store (parseNum num)::parse tail)
           | #"\n" => parse tail
           | #"." => [Stop]
           | _ => error "unknown instruction")

val parseCode =
 fn cs => let val p = parse cs 
                  handle Error => []
          in  T p
          end

end
